home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / admin / xinetd.2 / xinetd / xinetd.2.1.7-linux.4 / libs / src / misc / ftwx.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-09-10  |  3.9 KB  |  192 lines

  1. /*
  2.  * (c) Copyright 1992 by Panagiotis Tsirigotis
  3.  * All rights reserved.  The file named COPYRIGHT specifies the terms 
  4.  * and conditions for redistribution.
  5.  */
  6.  
  7. static char RCSid[] = "$Id: ftwx.c,v 1.6 1995/09/10 18:32:56 chuck Exp $" ;
  8.  
  9. #include <sys/param.h>
  10. #ifdef linux
  11. #include <unistd.h>
  12. #endif    /* linux */
  13. #include <sys/types.h>
  14. #include <sys/stat.h>
  15. #include <sys/file.h>
  16. #ifndef OLD_DIR
  17. #include <dirent.h>
  18. #else
  19. #include <sys/dir.h>
  20. #define dirent direct
  21. #endif
  22.  
  23. extern int errno ;
  24.  
  25. #include "misc.h"
  26. #include "ftwx.h"
  27.  
  28. #define PRIVATE            static
  29.  
  30. #define NUL                    '\0'
  31.  
  32. #if defined(linux) || defined(BSD)
  33. PRIVATE int ftwx_traverse( char *path , int depth ) ;
  34. #endif
  35.  
  36. typedef enum { NO, YES } boolean_e ;
  37.  
  38. static struct
  39. {
  40.     int (*stat_func)() ;
  41.     int (*user_func)() ;
  42. } ftwx_data ;
  43.  
  44. /*
  45.  * ftwx is an extension to ftw, that optionally follows symlinks (the
  46.  * default is NOT to follow them).
  47.  *
  48.  * Possible flag values:
  49.  *        FTWX_FOLLOW:         follow symlinks
  50.  *
  51.  * Possible depth values:
  52.  *        0            : means only the specified path
  53.  *        positive : means go as deep as specified
  54.  *        FTWX_ALL : no depth limitation
  55.  *
  56.  * User function return value:
  57.  *        negative : means an error occured and the traversal should stop
  58.  *        0            : OK
  59.  *        positive : means that if the current object is a directory it
  60.  *                      should not be traversed.
  61.  *
  62.  * Return value:
  63.  *        -1         : if an error occurs
  64.  *  frv            : frv is the function return value if it is negative (it
  65.  *                      should not be -1).
  66.  *        0            : if successful
  67.  */
  68. int ftwx( path, func, depth, flags )
  69.     char *path ;
  70.     int (*func)() ;
  71.     int depth ;
  72.     int flags ;
  73. {
  74.     int stat(), lstat() ;
  75.  
  76.     /*
  77.      * Initialize the data structure
  78.      */
  79.     ftwx_data.stat_func = ( flags & FTWX_FOLLOW ) ? stat : lstat ;
  80.     ftwx_data.user_func = func ;
  81.  
  82.     return( ftwx_traverse( path, depth ) ) ;
  83. }
  84.  
  85.  
  86.  
  87.  
  88. /*
  89.  * ftwx_traverse works in two phases:
  90.  *
  91.  * Phase 1: process the current path
  92.  *
  93.  * Phase 2: if the current path is a directory, it invokes ftwx_traverse
  94.  *                for each directory entry
  95.  */
  96. PRIVATE int ftwx_traverse( path, depth )
  97.     char *path ;
  98.     int depth ;
  99. {
  100.     DIR *dirp ;
  101.     struct stat st ;
  102.     int ftw_flag = 0 ;
  103.     boolean_e traverse = YES ;
  104.     int retval ;
  105.     int save_errno ;
  106.  
  107.     if ( (*ftwx_data.stat_func)( path, &st ) == -1 )
  108.         ftw_flag = FTW_NS ;
  109.     else
  110.     {
  111.         /*
  112.          * If it is a directory and determine if it is readable
  113.          * (if it is not readable, we don't traverse it
  114.          */
  115.         if ( S_ISDIR( st.st_mode ) )
  116.             if ( access( path, R_OK ) == 0 )
  117.                 ftw_flag = FTW_D ;
  118.             else
  119.                 ftw_flag = FTW_DNR ;
  120.         else
  121.             ftw_flag = FTW_F ;
  122.     }
  123.     retval = (*ftwx_data.user_func)( path, &st, ftw_flag ) ;
  124.     if ( retval < 0 )
  125.         return( retval ) ;
  126.     else if ( retval > 0 && ftw_flag == FTW_D )
  127.         traverse = NO ;
  128.  
  129.     /*
  130.      * Stop traversal if:
  131.      *        a. depth reached 0
  132.      *        b. the current path is not a readable directory
  133.      *        c. the user doesn't want us to traverse this directory tree
  134.      */
  135.     if ( depth == 0 || ftw_flag != FTW_D || traverse == NO )
  136.         return( 0 ) ;
  137.  
  138.     if ( depth != FTWX_ALL )
  139.         depth-- ;
  140.  
  141.     if ( ( dirp = opendir( path ) ) == NULL )
  142.         return( -1 ) ;
  143.  
  144.     for ( ;; )
  145.     {
  146.         struct dirent *dp ;
  147.         char *filename ;
  148.  
  149.         errno = 0 ;            /* to detect readdir errors */
  150.         dp = readdir( dirp ) ;
  151.         if ( dp == NULL )
  152.         {
  153.             retval = ( errno == 0 ) ? 0 : -1 ;
  154.             break ;
  155.         }
  156.  
  157.         /*
  158.          * The special names: "." and ".." are skipped
  159.          */
  160.         if ( dp->d_name[ 0 ] == '.' )
  161.             if ( dp->d_name[ 1 ] == NUL ||
  162.                         dp->d_name[ 1 ] == '.' && dp->d_name[ 2 ] == NUL )
  163.                 continue ;
  164.  
  165.         filename = make_pathname( 2, path, dp->d_name ) ;
  166.         if ( filename == NULL )
  167.         {
  168.             retval = -1 ;
  169.             break ;
  170.         }
  171.         
  172.         retval = ftwx_traverse( filename, depth ) ;
  173.         free( filename ) ;
  174.  
  175.         /*
  176.          * Check for a negative value instead of -1 because the
  177.          * user function may use any negative value
  178.          */
  179.         if ( retval < 0 )
  180.             break ;
  181.     }
  182.     /*
  183.      * Make sure we don't trash errno; we should only do this if
  184.      * retval is negative, but we are lazy...
  185.      */
  186.     save_errno = errno ;
  187.     (void) closedir( dirp ) ;
  188.     errno = save_errno ;
  189.     return( retval ) ;
  190. }
  191.  
  192.